﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlueLotus7.ArchiveSystem.Common;
using BlueLotus7.ArchiveSystem.WCFClients;
using System.Threading;

namespace BlueLotus7.ArchiveSystem
{
    public abstract class StatusMonitor : IStatusMonitor
    {
        #region Fields

        protected List<IStatusMonitorTask> tasks = new List<IStatusMonitorTask>();
        protected Guid domainScopeKey;
        protected Guid monitorClientKey;
        protected DateTime? needSyncStamp = null;
        protected DateTime? lastSyncStamp = null;
        protected Thread syncThread = null;
        protected bool isRunning = false;

        #endregion

        #region Properties

        public Guid DomainScopeKey
        {
            get { return this.domainScopeKey; }
        }

        public Guid MonitorClientKey
        {
            get { return this.monitorClientKey; }
        }

        public virtual string ScopeCode
        {
            get { return string.Empty; }
        }

        public List<IStatusMonitorTask> Tasks
        {
            get
            {
                return tasks;
            }
        }

        #endregion

        #region Constructor

        public StatusMonitor(Guid domainScopeKey, Guid monitorClientKey)
        {
            this.domainScopeKey = domainScopeKey;
            this.monitorClientKey = monitorClientKey;
        }

        #endregion

        #region Public Methods

        //public virtual void StartWatching()
        //{
        //    foreach (var t in this.tasks)
        //    {
        //        t.Start();
        //    }
        //}

        //public virtual void EndWatching()
        //{
        //    foreach (var t in this.tasks)
        //    {
        //        t.Stop();
        //    }
        //}

        public void Start()
        {
            if (syncThread == null)
            {
                isRunning = true;
                syncThread = new Thread(new ThreadStart(SyncThreadExecution));
                syncThread.IsBackground = true;
                syncThread.Start();
            }
        }

        public void Dispose()
        {
            foreach (var t in this.tasks)
            {
                t.Stop();
            }
        }

        protected void SyncTasks()
        {
            if (this.lastSyncStamp == null || this.lastSyncStamp.Value < this.needSyncStamp || (DateTime.Now - this.lastSyncStamp.Value).Seconds > 300)
            {
                List<DomainScopeUser> users = null;
                using (ArchiveStatusServiceClient client = Global.ServiceClient)
                {
                    users = client.RetrieveScopeUsersToMonitor(this.domainScopeKey, this.monitorClientKey);
                }

                if (users != null)
                {
                    //Delete
                    foreach (var one in this.tasks)
                    {
                        bool found = false;
                        foreach (var u in users)
                        {
                            if (u.Key == one.DomainScopeUserKey && u.MonitorStatus)
                            {
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            one.Stop();
                        }
                    }

                    //Add
                    foreach (var u in users)
                    {
                        if (u.MonitorStatus)
                        {
                            bool found = false;
                            foreach (var one in this.tasks)
                            {
                                if (u.Key == one.DomainScopeUserKey)
                                {
                                    found = true;
                                    break;
                                }
                            }

                            if (!found)
                            {
                                IStatusMonitorTask task = CreateTask(u.Key, u.ThirdPartyIdentity);
                                this.tasks.Add(task);
                                task.Start();
                            }
                        }
                    }
                }
            }

            this.lastSyncStamp = DateTime.Now;
        }

        public void SyncThreadExecution()
        {
            while (this.isRunning)
            {
                SyncTasks();

                Thread.Sleep(5000);
            }
        }

        public void UpdateSyncStamp()
        {
            this.needSyncStamp = DateTime.Now;
        }

        #endregion

        #region Protected Methods

        protected abstract IStatusMonitorTask CreateTask(Guid domainScopeUserKey, string thirdParyIdentity);

        #endregion


    }
}
